package com.weilan.ark3.serial;


import com.weilan.ark3.common.GlobalParam;
import com.weilan.ark3.entity.ControlDto;
import com.weilan.ark3.service.ModbusConfService;
import com.google.common.primitives.Shorts;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.msg.*;
import com.serotonin.modbus4j.serial.SerialPortWrapper;
import com.weilan.ark3.utils.ComFault;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 操作AC
 */
@Component
@Slf4j
public class SerialPortCom2Service {

    @Resource
    private ModbusConfService modbusConfService;
    /**
     * 串口波特率
     */
    //@Value("${modbus.rtu.baudRate}")
    private int BAUD_RATE = 9600;
    private int Data_Bits = 8;
    private int StopBits = 1;
    private int Parity = 0;
    private int FlowControlIn = 0;
    private int FlowControlOut = 0;

    /**
     * 串口名称
     */
    private String SERIAL_PORT = "COM2";
    //private String SERIAL_PORT = "COM9";

    //主站
    private static ModbusMaster master;

    private final static int READ_LEN = 120;


    /**
     * 根据协议读取模块数据
     *
     * @param slaveId 从站地址
     * @param start   起始地址的偏移量
     * @param len     待读寄存器的个数
     */
    public List<Short> readRTUHoldingRegisters(int slaveId, int start, int len) {
        if (master == null) {
            master = getRTUModbusMaster(SERIAL_PORT);
        }
        ReadHoldingRegistersResponse response = null;
        List<Short> readAllData = new ArrayList<>();
        try {
            while (len > READ_LEN) {
                ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start, len > READ_LEN ? READ_LEN : len);
                response = (ReadHoldingRegistersResponse) master.send(request);
                len -= 100;
                log.info(Arrays.toString(response.getShortData()));
                readAllData.addAll(Shorts.asList(response.getShortData()));
            }
            ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start, len > READ_LEN ? READ_LEN : len);
            response = (ReadHoldingRegistersResponse) master.send(request);
            log.info("modbus读取到数据：{}", readAllData);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("读保持寄存器错误，错误信息是：{}" + e.getMessage());
            master.destroy();
        }
        return readAllData;
    }


    /**
     * 读保持寄存器上的内容
     *
     * @param slaveId
     * @param start
     * @param len
     * @return
     */
    public short[] readRtuData(int slaveId, int start, int len) {
        int a = 0;
        int b = 0;
        if (master == null) {
            master = getRTUModbusMaster(SERIAL_PORT);
        }
        ReadInputRegistersResponse ameter = null;
        try {
                ReadInputRegistersRequest request_ameter = new ReadInputRegistersRequest(slaveId, start, len > READ_LEN ? READ_LEN : len);
                ameter = (ReadInputRegistersResponse) master.send(request_ameter);
        } catch (Exception e) {
            ComFault.CommunicationInterrupt(slaveId);
            modbusConfService.writerToEMS();
            e.printStackTrace();
        }
        if (ameter.getShortData() != null && ameter != null) {
            short[] shortData = ameter.getShortData();
            ComFault.CommunicationReserve(slaveId);
            modbusConfService.writerToEMS();
            return shortData;
        } else {
            return null;
        }
    }


    /**
     * 写单个保持寄存器
     *
     * @param controlDto 控制传输对象
     */
    public void writeRegister(ControlDto controlDto) {
        try {
            Integer slaveId = controlDto.getSlaveId();
            Integer offset = controlDto.getAddress();
            Integer value = controlDto.getValue();
            WriteRegisterRequest request = new WriteRegisterRequest(slaveId, offset, value);
            WriteRegisterResponse response = (WriteRegisterResponse) master.send(request);
            int writeOffset = response.getWriteOffset();
            int writeValue = response.getWriteValue();
            log.info("写保持寄存器地址：{}成功，值是：{}", writeOffset, writeValue);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("写保持寄存器异常，错误信息是：{}" + e.getMessage());
        }
    }


    private ModbusMaster getRTUModbusMaster(String serialPort) {
        ModbusMaster master = null;
        try {
            SerialPortWrapper serialParameters = new
                    SerialPortWrapperImpl(serialPort, BAUD_RATE, Data_Bits, StopBits, Parity, FlowControlIn, FlowControlOut);
            /* 创建ModbusFactory工厂实例 */
            ModbusFactory modbusFactory = new ModbusFactory();
            /* 创建ModbusMaster实例 */
            master = modbusFactory.createRtuMaster(serialParameters);
            master.init();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //设置超时时间
        master.setTimeout(500);
        //}
        return master;
    }
}
